﻿#include <opencv4/opencv2/opencv.hpp>
#include <opencv4/opencv2/highgui.hpp>
#include "camera/Inc/camera.h"

#include<QDebug>
#include <iostream>

cv::Mat src;

Mycamera::Mycamera() : image(MAT_HEIGHT, MAT_WIDTH, CV_8UC3, (0, 0, 0))
{
    nRet = MV_OK; //flag
    stImageInfo = {0};
    pData = (unsigned char *)malloc(sizeof(unsigned char) * MAX_IMAGE_DATA_SIZE);
    nDataSize = MAX_IMAGE_DATA_SIZE; //最大尺寸
    //pDataForRGB = (unsigned char *)malloc(stImageInfo.nWidth * stImageInfo.nHeight * 4 + 2048); //相机图片转化为RGB格式
    pDataForRGB = NULL;
    pDataForSaveImage = NULL;
    nIndex = 0;
    cameraisopen = false;
    breakflag = false;
    endmain_flag = 0;
}
/*
设置伽马矫正，如果设置将对应的注释去掉
 */
bool Mycamera::setVideoGamma()
{
    nRet = MV_CC_SetGammaSelector(handle, camera_param.MyGammaEnable);
    if (MV_OK != nRet)
    {
        qDebug() << "setVideoGamma fail!" << nRet << "\n";
        return false;
    }
    else
    {
        nRet = MV_CC_SetGamma(handle, camera_param.MyGamma);
        if (MV_OK != nRet)
        {
            qDebug() << "setVideoGamma fail!\n";
            return false;
        }
    }
    return true;
}
/*
自动设置帧率\
 */
bool Mycamera::setVideoExposureTime(int exposureTime)
{
  nRet = MV_CC_SetFloatValue(handle, "ExposureTime", exposureTime);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_SetExposureTime fail!\n";
        return false;
    }
    return true;
}

bool Mycamera::setVideoTriggerMode()
{
    //设置触发方式，一般为关闭
    nRet = MV_CC_SetTriggerMode(handle, 0);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_SetTriggerMode fail! nRet [%x]\n";
        return false;
    }
    return true;
}

bool Mycamera::setVideoHeight(int height)
{
        // 宽高设置时需考虑步进(16)，即设置宽高需16的倍数
        nRet = MV_CC_SetIntValue(handle, "Height",height);
        if (MV_OK == nRet)
        {
            qDebug() << "set height OK!" <<endl;
                        return true;
        }
        else
        {
            qDebug() << "set height failed! nRet [%x]" << endl;
                        return 	false;
        }
}

bool Mycamera::setVideoWidth(int width)
{
        // 宽高设置时需考虑步进(16)，即设置宽高需16的倍数
        nRet = MV_CC_SetIntValue(handle, "Width", width);
        if (MV_OK == nRet)
        {
            qDebug() << "set Width OK!" << endl;
                        return true;
        }
        else
        {
            qDebug() << "set Width failed! nRet [%x]" << endl;
                        return 	false;
        }
}

bool Mycamera::setVideoAOIX(int aoiX)
{
        // 宽高设置时需考虑步进(16)，即设置宽高需16的倍数
        nRet = MV_CC_SetAOIoffsetX(handle , aoiX);
        if (MV_OK == nRet)
        {
            qDebug() << "set AOIoffsetX OK!" << endl;
                        return true;
        }
        else
        {
            qDebug() << "set AOIoffsetX failed! nRet [%x]" << endl;;
                        return 	false;
        }
}

bool Mycamera::setVideoAOIY(int aoiY)
{
        // 宽高设置时需考虑步进(16)，即设置宽高需16的倍数
        nRet = MV_CC_SetAOIoffsetY(handle , aoiY);
        if (MV_OK == nRet)
        {
            qDebug()<<"set AOIoffsetY OK!"<<endl;
                        return true;
        }
        else
        {
            qDebug()<<"set AOIoffsetY failed! nRet [%x]"<<endl;;
                        return 	false;
        }
}

bool Mycamera::setVideoparam(int width,int height ,int aoiX ,int aoiY ,int exposureTime)
{
    if (!setVideoWidth(width))
    {
        return false;
    }
    if (!setVideoHeight(height))
    {
        return false;
    }
    if (!setVideoAOIY(aoiX))
    {
        return false;
    }
    if (!setVideoAOIX(aoiY))
    {
        return false;
    }
    //触发方式
    if (!setVideoTriggerMode())
    {
        return false;
    }
    //设置曝光
    if (!setVideoExposureTime(exposureTime))
    {
        return false;
    }
    return true;
}

bool Mycamera::open(int cameraIndex)
{
    cameraisopen = false;
    memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));
    nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList); //查找设备
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_EnumDevices fail! nRet [%x]\n";
        return false;
    }
    if (stDeviceList.nDeviceNum > 0)
    {
        nIndex = cameraIndex;
    }
    else
    {
      //qDebug() << "Find No Devices!\n" ;
      return false;
    }
    //创建句柄
    nRet = MV_CC_CreateHandle(&handle, stDeviceList.pDeviceInfo[nIndex]);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_CreateHandle fail! nRet [%x]\n";
        return false;
    }
    // 打开设备
    // open device
    nRet = MV_CC_OpenDevice(handle);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_OpenDevice fail! nRet [%x]\n";
        return false;
    }
    cameraisopen = true;
    qDebug() << "camia is open";
    return true;
}

bool Mycamera::isOpened() const
{
    if (cameraisopen == true)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Mycamera::startStream()
{
    nRet = MV_CC_StartGrabbing(handle);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_StartGrabbing fail! nRet [%x]\n";
        return false;
    }
    return true;
}

bool Mycamera::closeStream()
{
    nRet = MV_CC_StopGrabbing(handle);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_StopGrabbing fail! nRet [%x]\n";
        return false;
    }
    return true;
}

bool Mycamera::destoryVideo()
{
    nRet = MV_CC_DestroyHandle(handle);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_DestroyHandle fail! nRet [%x]\n";
        return false;
    }

    if (pData)
    {
        free(pData);
        pData = NULL;
    }
    if (pDataForRGB)
    {
        free(pDataForRGB);
        pDataForRGB = NULL;
    }
    if (pDataForSaveImage)
    {
        free(pDataForSaveImage);
        pDataForSaveImage = NULL;
    }
    return true;
}

bool Mycamera::rgbtocv()
{
    image = cv::Mat(MAT_HEIGHT, MAT_WIDTH, CV_8UC3, pDataForRGB);
    if (image.empty())
    {
        qDebug() << "转换失败";
        return false;
    }
    free(pDataForRGB);
    return true;
}

cv::Mat Mycamera::getiamge(void)
{
    //lock_.lock();
    cv::Mat temp_imag;
    image.copyTo(temp_imag);
    //lock_.unlock();

    return image;
}

bool Mycamera::getVideoimage()
{
    nRet = MV_CC_GetOneFrameTimeout(handle, pData, nDataSize, &stImageInfo, 1000);
    pDataForRGB = (unsigned char *)malloc(stImageInfo.nWidth * stImageInfo.nHeight * 4 + 2048);
    if (NULL == pDataForRGB)
    {
        breakflag = true;
        return false;
    }
    // DLOG_ERROR<<nDataSize<<endl;
    if (nRet == MV_OK)
    {
        // DLOG_ERROR<<"Now you GetOneFrame, Width[%d], Height[%d], nFrameNum[%d]\n\n"<<
        // stImageInfo.nWidth<< stImageInfo.nHeight<< stImageInfo.nFrameNum<<std::endl;
    }
    else
    {
        qDebug() << "get picture from video failed";
        return false;
    }
    if (pDataForRGB == NULL)
    {
        qDebug() << "内存申请失败";
        return false;
    }
    MV_CC_PIXEL_CONVERT_PARAM stConvertParam = {0};
    stConvertParam.nWidth = stImageInfo.nWidth;
    stConvertParam.nHeight = stImageInfo.nHeight;
    stConvertParam.pSrcData = pData;
    stConvertParam.nSrcDataLen = stImageInfo.nFrameLen;
    stConvertParam.enSrcPixelType = stImageInfo.enPixelType;
    stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed;
    stConvertParam.pDstBuffer = pDataForRGB;
    stConvertParam.nDstBufferSize = stImageInfo.nWidth * stImageInfo.nHeight *4 + 2048;
    nRet = MV_CC_ConvertPixelType(handle, &stConvertParam);
    if (MV_OK != nRet)
    {
        qDebug() << "MV_CC_ConvertPixelType fail! nRet [%x]\n";
        return false;
    }
    return true;
}

Mycamera::~Mycamera()
{
    destoryVideo();
}
